package com.numberencoding;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NumberEncoder {
    private final Map<Character, String> digitToLettersMap;

    private final Trie dictionary;
    
    public NumberEncoder(String dictionaryPath) {
        digitToLettersMap = new HashMap<Character, String>();

        dictionary = new Trie();
        
        initMappings();

        preloadDictionary(dictionaryPath);
    }

    private void initMappings() {
        digitToLettersMap.put('0', "Ee");
        digitToLettersMap.put('1', "JNQjnq");
        digitToLettersMap.put('2', "RWXrwx");
        digitToLettersMap.put('3', "DSYdsy");
        digitToLettersMap.put('4', "FTft");
        digitToLettersMap.put('5', "AMam");
        digitToLettersMap.put('6', "CIVciv");
        digitToLettersMap.put('7', "BKUbku");
        digitToLettersMap.put('8', "LOPlop");
        digitToLettersMap.put('9', "GHZghz");
    }

    private void preloadDictionary(String fileName) {
        // create Trie and load all words

        BufferedReader br = null;
        try {
            FileInputStream fis = new FileInputStream(fileName);

            br = new BufferedReader(new InputStreamReader(fis));

            String line;

            while ((line = br.readLine()) != null) {
                addWordToDictionary(line);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void addWordToDictionary(String line) {
        dictionary.insertString(line);
    }

    public void processData(String fileName) {
        BufferedReader br = null;
        try {
            FileInputStream fis = new FileInputStream(fileName);

            br = new BufferedReader(new InputStreamReader(fis));

            String line;

            while ((line = br.readLine()) != null) {
                processNumber(line);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void processNumber(String number) {
        StringBuilder numberBuilder = new StringBuilder();
        for (int i = 0; i < number.length(); i++) {
            if (Character.isDigit(number.charAt(i))) {
            	numberBuilder.append(number.charAt(i));
            }
        }
        
        
        
        processNumber(number, numberBuilder.toString(), 0, "");
     
    }

	private void processNumber(String number, String digits, int index, String current) {
		checkWord(number, digits, current);
		
		if (index == digits.length()) {
			return;
		} else {
			String letters = digitToLettersMap.get(digits.charAt(index));
			for (int i = 0; i < letters.length(); i++) {
				//if (isPrefixExists(current)) {
					processNumber(number, digits, index + 1, current + letters.charAt(i));
				//}
			}
		}
	}

	private void checkWord(String number, String digits, String current) {
		if (digits.length() == current.length()) {
			List<String> words = new ArrayList<String>();
			
			String result = dictionary.findAllWords(digits, current, words);
			if (result != null && digits != null) {
				String res = null;
				
				StringBuilder b = new StringBuilder();
				for (int i=0; i < words.size(); i++) {
					b.append(words.get(i));
					
					if (i < words.size() - 1) {
						b.append(" ");	
					}
					
					if (current.equals(words.get(i))) {
						res = words.get(i);
					}
				}
				
				if (res == null) {
					res = b.toString();
				}
				
				System.out.println(number + ": " + res);
			}
		}
	}


	private boolean isPrefixExists(String prefix) {
        return dictionary.isPrefixExists(prefix);
    }
    
    public static void main(String[] args) {
        if (args.length == 2) {
            NumberEncoder encoder = new NumberEncoder(args[0]);
            encoder.processData(args[1]);
        }

    }
}
